#include "Task.hpp"
#include <string>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/stat.h>


const int processNum = 10;
vector<task_t> tasks;//？为什么要放这里

//先描述
class channel
{
public:
    channel(int cmdfd,int slaverid,const string &processName)
    :_cmdfd(cmdfd)
    ,_slaverid(slaverid)
    ,_processName(processName)
    { }

public:
    int _cmdfd;//发送文件的描述符
    pid_t _slaverid;//子进程pid
    string _processName;//子进程名字，方便打印日志
};

// void slaver(int rfd)
// {
//     while(1)
//     {
//         cout << "read rfd is: " << rfd << endl;
//         sleep(5);
//     }
// }
void slaver()
{
    while(1)
    {
        int cmdcode = 0;
        int n = read(0,&cmdcode,sizeof(int));
        if(n == sizeof(int))
        {
            //读取完毕，取到任务码
            cout << "子进程: " << getpid() << "开始执行任务: " << cmdcode << endl;
            
            if(cmdcode >= 0 || cmdcode < tasks.size())
            {
                tasks[cmdcode]();
            }
        }
        if(n == 0) break;
        sleep(1);
    }
}

//组织
void InitProcessPool(vector<channel>* channels)
{//传参
    //输入 const &
    //输出 指针*
    //输入输出 引用&
    for(int i = 0; i < processNum; i++)
    {
        int pipefd[2];
        int n = pipe(pipefd);
        assert(n == 0);
        (void)n;

        pid_t id = fork();
        if(id == 0)
        {
            close(pipefd[1]);
            dup2(pipefd[0],0);//子进程从管道读重定向为 “从标准输入流读”（应当理解为标准输入流重定向到管道3）
            slaver();
            //slaver(pipefd[0]);//子进程执行任务
            cout << "quit: " << getpid() << endl;
            exit(0);
        }

            //父
        close(pipefd[0]);
        string name = "process-" + to_string(i); // 0~5进程名
        channels->push_back(channel(pipefd[1],id,name));
    }
}

//测试
void Debug(const vector<channel>& channels)
{//传参
    //输入 const &
    //输出 指针*
    //输入输出 引用&
    for(auto &ch : channels)
    {
        cout<< ch._cmdfd << " " << ch._slaverid << " " << ch._processName << endl;
    }
}

void ctrlSlaver(const vector<channel>& channels)
{
    // for(int i = 0; i < 100; i++)
    // {
    //     //选择任务码执行任务
    //     int cmdcode = rand()%tasks.size();

    //     //选择子进程
    //     int processcode = rand()%channels.size();
    //     cout << "父进程发送任务码: " << cmdcode << "给子进程: " << channels[processcode]._slaverid << endl; 

    //     //发送任务
    //     write(channels[processcode]._cmdfd,&cmdcode,sizeof(cmdcode));
    // }


    int which = 0;//轮询进程
    int cnt = 10;
    while(cnt)
    {
        //选择任务码执行任务
        int cmdcode = rand()%tasks.size();

        //选择子进程
        int processcode = rand()%channels.size();
        cout << "父进程发送任务码: " << cmdcode << "给子进程: " << channels[processcode]._slaverid << endl; 

        //发送任务
        write(channels[processcode]._cmdfd,&cmdcode,sizeof(cmdcode));
        cnt--;
    }
    which++;
    which &= channels.size();//防止which越界
}


void quitProcess(const vector<channel>& channels)
{
    for(const auto ch : channels)
    {
        close(ch._cmdfd);
    }

    sleep(10);

    for(const auto ch: channels)
    {
        waitpid(ch._slaverid,nullptr,0);
    }
    sleep(5);
}
int main()
{
    srand(time(nullptr)^getpid()^1023);//种随机数种子
    LoadTask(&tasks);
    vector<channel> channels;

    InitProcessPool(&channels);
    Debug(channels); 
    ctrlSlaver(channels);
    quitProcess(channels);

    return 0;
}